//给自己写的备注：
//1、SX1262和SX1278的引脚定义不同，SX1262包括中断引脚LORA_BUSY，SX1278没有；
//2、SX1262的中断引脚为DIO1，SX1278的中断引脚为DIO0；
//3、SX1262的初始化方式不同.
//4、SX1262的接收方式不同.
#include <RadioLib.h>
#include <Arduino.h>
// 预处理指令集中管理配置
// 公共部分
#define LORA_SCK   10
#define LORA_MISO  6
#define LORA_MOSI  7
#define LORA_NSS   8
#define LORA_RST   5    
#if defined(USE_SX1262)
//SX1262 配置
#define LORA_BUSY  4  
#define LORA_DIO1  3
// SX1262专用模块对象
Module loraModule(LORA_NSS, LORA_DIO1, LORA_RST, LORA_BUSY);
SX1262 radio = SX1262(&loraModule);

#elif defined(USE_SX1278)
//SX1278 配置
#define LORA_DIO0 3
// SX1278专用模块对象
Module loraModule(LORA_NSS, LORA_DIO0, LORA_RST);
SX1278 radio = SX1278(&loraModule);

#endif

// 公共配置参数
const float FREQ = 470.0;   // 优先使用低频段
const int SF = 12;          // 保持最大扩频因子
const float BW = 41.7;      // 最小可用带宽（最大化灵敏度）
const int CR = 8;           // 最高冗余编码
const int PWR = 17;         // 法规允许最大功率

// 全局接收标志
volatile bool receivedFlag = false;

// 添加丢包率计算变量
int startSeq = -1;          // 记录第一个收到的序列号
int receivedCount = 0;      // 成功接收次数

// 中断回调函数
void setReceiveFlag(void) {
  receivedFlag = true;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  //SPI初始化
  #if defined(USE_SX1262)
  SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI); // SX1262需要显式指定SPI引脚
  #elif defined(USE_SX1278)
  SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_NSS); // SX1278需要NSS引脚
  #endif

  //芯片初始化
  int state = radio.begin(FREQ); // 频率（根据地区设置，如中国470-510MHz）
  
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println("LoRa 初始化成功！");
  } else {
    Serial.print("初始化失败，错误代码：");
    Serial.println(state);
    while (true);
  }

  /************** 参数配置 **************/
  // 公共参数配置
  radio.setSpreadingFactor(SF);
  radio.setBandwidth(BW);
  radio.setCodingRate(CR);
  radio.setOutputPower(PWR);

  #if defined(USE_SX1262)
  // 设置接收回调SX1262
  radio.setDio1Action(setReceiveFlag);
  #elif defined(USE_SX1278)
  // 设置中断回调SX1278
  radio.setDio0Action(setReceiveFlag, RISING); 
  #endif

  // 开始持续监听
  Serial.print("开始监听...");
  state = radio.startReceive();
  if (state != RADIOLIB_ERR_NONE) {
    Serial.print("监听启动失败，错误代码：");
    Serial.println(state);
    while(true);
  }
  Serial.println("成功！");
}

void loop() {
  // 当收到中断标志时处理数据
  if(receivedFlag) {
    receivedFlag = false; // 清除标志
    
    String receivedData;
    int state = radio.readData(receivedData);
    
    if(state == RADIOLIB_ERR_NONE) {
      // 转换接收到的数据为整数
      int currentSeq = receivedData.toInt();
      
      // 如果是第一个包，记录起始序列号
      if(startSeq == -1) {
        startSeq = currentSeq;
        receivedCount = 1;
        Serial.print("设置起始序号: ");
        Serial.println(startSeq);
      } 
      // 后续包
      else {
        receivedCount++;
      }
      
      // 计算应该接收的次数 = 当前序号 - 起始序号 + 1
      int expectedCount = currentSeq - startSeq + 1;
      
      // 计算实时丢包率
      float lossRate = 0.0;
      if (expectedCount > 0) {
        lossRate = (1.0 - (float)receivedCount / (float)expectedCount) * 100.0;
      }
      
      Serial.print("当前序号: ");
      Serial.print(currentSeq);
      Serial.print(" | 接收次数: ");
      Serial.print(receivedCount);
      Serial.print(" | 应接收: ");
      Serial.print(expectedCount);
      Serial.print(" | 丢包率: ");
      Serial.print(lossRate, 1); // 保留1位小数
      Serial.println("%");
      
      // RSSI（接收信号强度）
      Serial.print("RSSI: ");
      Serial.print(radio.getRSSI());
      Serial.println(" dBm");
      
      // SNR（信噪比）
      Serial.print("SNR: ");
      Serial.print(radio.getSNR());
      Serial.println(" dB");
    } else {
      Serial.print("解码失败，错误代码：");
      Serial.println(state);
    }

    // 重新启用接收
    radio.startReceive();
  }
}


